<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
   <head>
      <title>EverRest Example</title>
   </head>
   <body>
      <h1>EverRest Example</h1>
      <p>This is sample of using EverRest to launch JAX-RS services.</p>
      <p>We will create simple places service. It should be able give access to places by id, get list all available places 
      and add new place in storage. Service supports JSON format for transfer data to/from client.</p>
   </body>
   <ul>
      <li>Add required <i>contex-param</i>.
      <pre>
      &lt;context-param&gt;
         &lt;param-name&gt;javax.ws.rs.Application&lt;/param-name&gt;
         &lt;param-value&gt;org.moyakarta.rest.PlaceApplication&lt;/param-value&gt;   
      &lt;/context-param&gt;
      </pre>
      <table border="1">
      <tbody>
      <tr>
      <th>Parameter</th>
      <th>Description</th>
      </tr>
      <tr>
      <td>javax.ws.rs.Application</td>
      <td>This is FQN of Java class that extends <i>javax.ws.rs.core.Application</i> and provides set of classes and(or)
      instances of JAX-RS components.</td>
      </tr>
      </tbody>
      </table></li>
      <li>Add bootstrap listeners.
      <p>Need add two listeners. First one initializes PlaceStorage and adds it to servlet context. The second one
      initializes common components of EverRest frameworks.</p>
      <pre>
      &lt;listener&gt;
         &lt;listener-class&gt;org.moyakarta.rest.PlaceServiceBootstrap&lt;/listener-class&gt;
      &lt;/listener&gt;
      &lt;listener&gt;
         &lt;listener-class&gt;org.everrest.core.servlet.EverrestInitializedListener&lt;/listener-class&gt;
      &lt;/listener&gt;
      </pre></li>
      <li>Add EverrestServlet.
      <pre>
      &lt;servlet&gt;
         &lt;servlet-name&gt;EverrestServlet&lt;/servlet-name&gt;
         &lt;servlet-class&gt;org.everrest.core.servlet.EverrestServlet&lt;/servlet-class&gt;
      &lt;/servlet&gt;
      &lt;servlet-mapping&gt;
         &lt;servlet-name&gt;EverrestServlet&lt;/servlet-name&gt;
         &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
      &lt;/servlet-mapping&gt;
      </pre></li>
      <li>EverRest components.
      <p><i>org.moyakarta.rest.PlaceApplication</i> - application deployer.</p>
      <pre>
      public class PlaceApplication extends Application
      {
         @Override
         public Set&lt;Class&lt;?&gt;&gt; getClasses()
         {
            Set&lt;Class&lt;?&gt;&gt; cls = new HashSet&lt;Class&lt;?&gt;&gt;(1);
            cls.add(PlaceService.class);
            return cls;
         }

         @Override
         public Set&lt;Object&gt; getSingletons()
         {
            Set&lt;Object&gt; objs = new HashSet&lt;Object&gt;(1);
            objs.add(new PlaceNotFoundExceptionMapper());
            return objs;
         }
      }
      </pre>
      <p><i>org.moyakarta.rest.Place</i> - simple Java Bean that will be used to transfer data via JSON.</p>
      <p><i>org.moyakarta.rest.PlaceNotFoundException</i> - exception that will be thrown by
      <i>org.moyakarta.rest.PlaceService</i> if client requested place that does not exist in storage.</p>
      <p><i>org.moyakarta.rest.PlaceNotFoundExceptionMapper</i> - JAX-RS component that intercepts
      <i>org.moyakarta.rest.PlaceNotFoundException</i> and send correct response to client.</p>
      <pre>
      @Provider
      public class PlaceNotFoundExceptionMapper implements ExceptionMapper&lt;PlaceNotFoundException&gt;
      {
         Response toResponse(PlaceNotFoundException exception)
         {
            return Response.status(404).entity(exception.getMessage()).type("text/plain").build();
         }
      }
      </pre>
      <p><i>org.moyakarta.rest.PlaceService</i> - JAX-RS service that process client's requests. Instance of
      <i>PlaceStorage</i> will be injected automatically thanks to <i>org.everrest.core.Inject</i> annotation</p>
      <pre>
      @Path("places")
      public class PlaceService
      {
         @Inject
         private PlaceStorage placeStorage;
      
         @Path("{id}")
         @GET
         @Produces("application/json")
         public Place get(@PathParam("id") String id) throws PlaceNotFoundException
         {
            Place place = placeStorage.getPlace(id);
            if (place == null)
               throw new PlaceNotFoundException(id);
            return place;
         }
      
         @GET
         @Produces("application/json")
         public Collection&lt;Place&gt; getAll()
         {
            return placeStorage.getAll();
         }
      
         @PUT
         @Consumes("application/json")
         public Response put(Place place, @Context UriInfo uriInfo)
         {
            String id = placeStorage.putPlace(place);
            URI location = uriInfo.getBaseUriBuilder().path(getClass()).path(id).build();
            return Response.created(location).entity(location.toString()).type("text/plain").build();
         }
      }
      </pre>
      <p><i>org.moyakarta.rest.PlaceStorage</i> - storage of Places.</p>
      <pre>
      public class PlaceStorage
      {
      
         private static int idCounter = 100;
      
         public synchronized String generateId()
         {
            idCounter++;
            return Integer.toString(idCounter);
         }
      
         private Map&lt;String, Place&gt; books = new ConcurrentHashMap&lt;String, Place&gt;();
      
         public PlaceStorage()
         {
            init();
         }
      
         private void init()
         {
            Place book = new Place();
            book.setTitle("JUnit in Action");
            book.setAuthor("Vincent Masson");
            book.setPages(386);
            book.setPrice(19.37);
            putPlace(book);
         }
      
         public Place getPlace(String id)
         {
            return books.get(id);
         }
      
         public String putPlace(Place book)
         {
            String id = book.getId();
            if (id == null || id.trim().length() == 0)
            {
               id = generateId();
               place.setId(id);
            }
            places.put(id, place);
            return id;
         }
      
         public Collection&lt;Place&gt; getAll()
         {
            return places.values();
         }
      
         public int numberOfPlaces()
         {
            return places.size();
         }
      }
      </pre></li>
         <li>Request mapping.
         <table border="1"><tbody>
         <tr>
         <th>Relative Path</th>
         <th>HTTP Method</th>
         <th>Description</th>
         </tr>
         <tr>
         <td>rest/places/{id}</td>
         <td>GET</td>
         <td>Get places with specified id. Just after server start only one place in storage and it can be accessed via
         id <i>101</i></td>
         </tr>
         <tr>
         <td>rest/places/</td>
         <td>GET</td>
         <td>Get all places from storage.</td>
         </tr>
         <tr>
         <td>rest/places/</td>
         <td>PUT</td>
         <td>Add new place in storage. The body of request must contains place's description in JSON format. The
         <i>Content-type</i> header must be set to <i>application/json</i></td>
         </tr>
         </tbody></table>
         </li>
         <li>How to try.
         <p>Build project.</p>
         <pre>mvn clean install</pre>
         <p>Run it with Jetty server.</p>
         <pre>mvn jetty:run</pre>
         <p>Point you web browser to <a href="http://localhost:8080/rest/places/101">http://localhost:8080/rest/places/101</a></p>
         <p>If you are under linux or other unix like OS the you can use <i>curl</i> utility (often it is already installed).
         Binary build of this utility available for windows also at <a href="http://curl.haxx.se/download.html">http://curl.haxx.se/download.html</a>.
         With <i>curl</i> you able to add new place in storage via command</p>
         <pre>
         curl -X PUT \
         -H "Content-type:application/json" \
         -d '{"author":"My Author","title":"My Title","price":1.00,"pages":100}' \
         http://localhost:8080/rest/places/ 
         </pre>
         </li>
      
   </ul>
</html>